//
//  CQBaseCardCollectionView.swift
//  TSListDemo
//
//  Created by qian on 2020/11/16.
//  Copyright © 2020 dvlproad. All rights reserved.
//

import Foundation

extension UICollectionView {
    private static var movetoPointKey: Character!
    var movetoPoint: CGPoint {
        set {
            objc_setAssociatedObject(self, &UICollectionView.movetoPointKey, newValue, .OBJC_ASSOCIATION_RETAIN)
        }
        get {
            return (objc_getAssociatedObject(self, &UICollectionView.movetoPointKey) as? CGPoint) ?? CGPoint.zero
        }
    }
}

/// 移动过程中的状态值
enum CQCardMoveState: NSInteger {
    case MoveInside = 0     // 在范围移动
    case MoveTooFastLeft    // 快速的左侧滑动
    case MoveTooFastRight   // 快速的左侧滑动
    case MoveOutLeft        // 移出左边了
    case MoveOutRight       // 移出右边了
}

/// 喜欢的类型
enum CQCardLikeType: NSInteger {
    case None = 0       // 未曾处理过
    case Like           // 喜欢
    case SuperLike      // 超级喜欢
    case Hate           // 讨厌
    case SuperHate      // 超级讨厌
}

class CQBaseCardCollectionView: UICollectionView {
    private var isLeft: Bool?
    fileprivate var isAnimating = false
    
    var allDataSource: [AnyObject] = [] // 需要显示的所有数据
    var showDataSource: [AnyObject] = [] // 屏幕上显示的cell数据源
    var insertIndex = 0 // 从allDataSource中拿一条数据 插入到showDataSource中
    let visibleCellsCount = 1 // 屏幕上显示cell的个数
    
    var pages = 0
    var limit = 10 // 每页限定10条数据
    
    var checkRemoveEnableBlock: ((_ moveState: CQCardMoveState)->(Bool))?  // 检测是否能够删除
    
    var panChangeBlock: ((_ isLeft: Bool, _ bCell: CQBaseCardCollectionViewCell, _ percentValue: CGFloat)->(Void))?
    var panCompleteBlock: ((_ likeType: CQCardLikeType, _ bCell: CQBaseCardCollectionViewCell)->(Void))?  // 清空时候
    
    
    
    @objc func addPanGest() {
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(self.panGestHandle(_:)))
        self.addGestureRecognizer(panGesture)
    }
    
    @objc private func panGestHandle(_ panGest: UIPanGestureRecognizer) {
        guard !isAnimating else { return }
        
        guard let cell = ((self.cellForItem(at:IndexPath(row: 0, section: 0) )) as? CQBaseCardCollectionViewCell), self.allDataSource.count > 1 else {
            return
        }
//        guard let lastCell = (self.cellForItem(at:IndexPath(row: self.visibleCellsCount - 1, section: 0))) else {
//            return
//        }
        let movePoint = panGest.translation(in: self)
        self.movetoPoint = movePoint
        if (panGest.state == .began) {
            for tempCell in self.visibleCells {
                guard let tempCardCell = tempCell as? CQBaseCardCollectionViewCell else { return }
                tempCardCell.originalCenter = CGPoint(x: tempCardCell.frame.origin.x + tempCardCell.frame.size.width/2, y: tempCardCell.frame.origin.y + tempCardCell.frame.size.height/2)
                tempCardCell.originalFrame = tempCardCell.frame
            }
            
        } else if (panGest.state == .changed) {
            cell.center = CGPoint(x: cell.center.x + movePoint.x, y: cell.center.y + movePoint.y )
            cell.currentAngle = (cell.center.x - cell.frame.size.width / 2.0) / cell.frame.size.width / 4.0;
            cell.transform = CGAffineTransform(rotationAngle: cell.currentAngle!)
            
            let cellNewCenterX = cell.center.x
            var cellNewCenterY = cell.center.y
            let cellOriginalCenterX = cell.originalCenter?.x ?? 0
            let cellOriginalCenterY = cell.originalCenter?.y ?? 0
            
            // 更新限制本移动Cell的 CenterY
            var moveOffsetY: CGFloat = cell.center.y - cellOriginalCenterY
            let moveBoundaryYMax: CGFloat = 40
            if moveOffsetY > moveBoundaryYMax {
                moveOffsetY = min(moveBoundaryYMax, moveOffsetY)
            }
            if moveOffsetY < -moveBoundaryYMax {
                moveOffsetY = max(-moveBoundaryYMax, moveOffsetY)
            }
            debugPrint("pan changed...moveOffsetY=\(moveOffsetY)")
            cellNewCenterY  = cellOriginalCenterY + moveOffsetY
            cell.center = CGPoint.init(x: cellNewCenterX, y: cellNewCenterY)
            
            // 处理 X
            let moveOffsetX: CGFloat = cell.center.x - cellOriginalCenterX
            let moveBoundaryXMin: CGFloat = 40
            let moveBoundaryXMax: CGFloat = 80
            let moveOffsetXPositive: CGFloat = abs(moveOffsetX)
            var movePercentValue: CGFloat = 0
            if moveOffsetXPositive < moveBoundaryXMin {
                movePercentValue = 0
            } else if moveOffsetXPositive >= moveBoundaryXMax {
                movePercentValue = 1
            } else {
                movePercentValue = (moveOffsetXPositive-moveBoundaryXMin)/(moveBoundaryXMax-moveBoundaryXMin)
            }
            debugPrint("pan changed...moveOffsetX=\(moveOffsetX), movePercentValue=\(movePercentValue)")
            
            if self.panChangeBlock != nil {
                if moveOffsetX < 0 {
                    self.panChangeBlock!(true, cell, movePercentValue)
                } else {
                    self.panChangeBlock!(false, cell, movePercentValue)
                }
            }
            
            
            isLeft = (moveOffsetX < 0)
            
            let movePointOffset = CGPoint(x: moveOffsetX, y: moveOffsetY)
            //self.__resetlayoutWithOffset(movePointOffset, exceptCell1: cell, exceptCell2: lastCell)
            self.__resetlayoutWithOffset(movePointOffset, exceptCell1: cell)
            panGest.setTranslation(.zero, in: self)
            
        } else if (panGest.state == .ended) {
            var moveState: CQCardMoveState = CQCardMoveState.MoveInside
            
            let vel = panGest.velocity(in: self) // 获取手势离开时在x,y方向的速度，单位是点每秒(逻辑尺寸点)。
            let centerOffsetX = UIScreen.main.bounds.size.width / 3.0
            debugPrint("拖动速率\(vel.x)") // [iOS 惯性滑动效果](https://www.jianshu.com/p/269a7d90f530)
            // 如果拖动超过一定速率，则进入下一张
            if (vel.x > centerOffsetX || vel.x < -centerOffsetX)  {
                if (vel.x > centerOffsetX)  {
                    moveState = CQCardMoveState.MoveTooFastRight
                } else {
                    moveState = CQCardMoveState.MoveTooFastLeft
                }
            } else {
                // 如果拖动没超过一定速率，则进行实际滑动终点位置比较
                //let removeLeftX: CGFloat =  150
                //let removeRightX: CGFloat = cell.frame.size.width - 150
                let collectionViewWidth: CGFloat = self.frame.size.width
                let removeLeftX: CGFloat =  collectionViewWidth/4*1 // 进入移出的左边界
                let removeRightX: CGFloat = collectionViewWidth/4*3 // 进入移出的由边界
                
                let cellMaxX: CGFloat = cell.frame.origin.x + cell.frame.size.width
                let cellMinX: CGFloat = cell.frame.origin.x
                let isRemoveFromLeft: Bool = cellMaxX < removeLeftX
                let isRemoveFromRight: Bool = cellMinX > removeRightX
                if (isRemoveFromLeft || isRemoveFromRight) {
                    if isRemoveFromLeft {
                        moveState = CQCardMoveState.MoveOutLeft
                    } else {
                        moveState = CQCardMoveState.MoveOutRight
                    }
                } else {
                    moveState = CQCardMoveState.MoveInside
                }
            }
            self.__panEnd(cell: cell, moveState: moveState)
        }
    }
    
    private func __panEnd(cell: CQBaseCardCollectionViewCell, moveState: CQCardMoveState) {
        var removeEnable: Bool = true
        if self.checkRemoveEnableBlock != nil {
            removeEnable = self.checkRemoveEnableBlock!(moveState)
        }
        
        if removeEnable {
            self.remove(cell: cell)
        } else {
            self.__resetPanningCell(cell: cell)
        }
        
        if self.panCompleteBlock == nil {
            return;
        }
        
        var likeType: CQCardLikeType
        switch moveState {
            case .MoveTooFastLeft, .MoveOutLeft:
                likeType = .Hate
                break
            case .MoveTooFastRight, .MoveOutRight:
                likeType = .Like
                break
            default:
                likeType = .None
                break
            }

        self.panCompleteBlock!(likeType, cell)
    }
    
    /// 对正在拖动的cell，进行恢复
    private func __resetPanningCell(cell: CQBaseCardCollectionViewCell) {
        UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseOut, animations: {
            cell.center = cell.originalCenter!
            cell.transform = CGAffineTransform(rotationAngle: 0)
            
            //self.__resetlayoutWithOffset(.zero, exceptCell1: cell, exceptCell2: lastCell)
            self.__resetlayoutWithOffset(.zero, exceptCell1: cell)
        })
    }
    
    /// 根据offset重置除exceptCell1(这个一般是目前拖动的那个cell)外的其他cell
//    private func __resetlayoutWithOffset(_ offset: CGPoint = .zero, exceptCell1: CQBaseCardCollectionViewCell, exceptCell2: CQBaseCardCollectionViewCell) {
//        let _ = self.visibleCells.filter({$0 !== exceptCell1 && $0 !== exceptCell2}).map({
    private func __resetlayoutWithOffset(_ offset: CGPoint = .zero, exceptCell1: CQBaseCardCollectionViewCell) {
        let _ = self.visibleCells.filter({$0 !== exceptCell1}).map({
            guard let card = $0 as? CQBaseCardCollectionViewCell else { return }
            
            let collectionViewLayout: CQTBaseCardCollectionViewFlowLayout = self.collectionViewLayout as! CQTBaseCardCollectionViewFlowLayout
            card.resetlayoutWithOffset(.zero, collectionViewLayout: collectionViewLayout)
        })
    }
    
    
    private func remove(cell: CQBaseCardCollectionViewCell) {
        isAnimating = true
        
        UIView.animate(withDuration: 0.3, animations: {
            let cellCurrentAngle: CGFloat = cell.currentAngle ?? 1
            let cellWidth: CGFloat = cell.frame.size.width
            let cellHeight: CGFloat = cell.frame.size.height
            if (self.isLeft!) { // left
                let cellCenterX = -cellWidth / 2
                cell.center = CGPoint(x: cellCenterX, y: cell.center.y - cellCurrentAngle * cellHeight);
            } else {            // right
                let screenWidth = UIScreen.main.bounds.width
                let cellCenterX = screenWidth + cellWidth / 2
                cell.center = CGPoint(x: cellCenterX, y: cell.center.y + cellCurrentAngle * cellHeight);
            }
        })
        
        
        
        cell.alpha = 0
        cell.center = cell.originalCenter ?? CGPoint.zero
        if self.insertIndex >= self.allDataSource.count {
            self.insertIndex = 0
        }
        self.showDataSource.remove(at: 0)
        self.deleteItems(at: [IndexPath(item: 0, section: 0)])
        self.performBatchUpdates({
//            self.showDataSource.append(self.allDataSource[self.insertIndex])
//            let insert = min(self.visibleCellsCount - 1, self.allDataSource.count - 1)
//            self.insertItems(at: [IndexPath(item: insert, section: 0)])
            
        }, completion: { (comlete) in
            self.isAnimating = !comlete
            // 计算可见cell的indexpath值
//            let cell1 = self.cellForItem(at:IndexPath(row: 0, section: 0) ) as! CQBaseCardCollectionViewCell
//            let lastCell = self.cellForItem(at:IndexPath(row: self.visibleCellsCount - 1, section: 0) ) as! CQBaseCardCollectionViewCell
//            let _ = self.visibleCells.filter({$0 !== cell1 && $0 !== lastCell}).map({
//                guard let card = $0 as? CQBaseCardCollectionViewCell else { return }
//                card.indexPathItem -= 1
//            })
        })
        
        self.insertIndex += 1
    }
    
    
    func synchronized(_ lock: Any, closure: () -> ()) {
        objc_sync_enter(lock)
        closure()
        objc_sync_exit(lock)
    }
}

